Load libraries

#library(ArchR)
library(knitr)
library(tidyverse)
library(Seurat)
library(SeuratData)
## Warning in if (is.na(desc)) {: the condition has length > 1 and only the first
## element will be used

## Warning in if (is.na(desc)) {: the condition has length > 1 and only the first
## element will be used

## Warning in if (is.na(desc)) {: the condition has length > 1 and only the first
## element will be used

## Warning in if (is.na(desc)) {: the condition has length > 1 and only the first
## element will be used

## Warning in if (is.na(desc)) {: the condition has length > 1 and only the first
## element will be used

## Warning in if (is.na(desc)) {: the condition has length > 1 and only the first
## element will be used

## Warning in if (is.na(desc)) {: the condition has length > 1 and only the first
## element will be used

## Warning in if (is.na(desc)) {: the condition has length > 1 and only the first
## element will be used

## Warning in if (is.na(desc)) {: the condition has length > 1 and only the first
## element will be used

## Warning in if (is.na(desc)) {: the condition has length > 1 and only the first
## element will be used

## Warning in if (is.na(desc)) {: the condition has length > 1 and only the first
## element will be used

## Warning in if (is.na(desc)) {: the condition has length > 1 and only the first
## element will be used
library(scater)
library(zellkonverter)
library(SingleCellExperiment)
library(EnsDb.Mmusculus.v79)
library(Signac)
#library(SeuratDisk)
#library(caret)
#h5disableFileLocking()

We can read in the .h5ad file as a SummarizedCellExperiment

rna_gastr_SE <- readH5AD("anndata_rna.h5ad")

We can convert a Seurat object to a SummarizedCellExperiment

SCE <- as.SingleCellExperiment(gastr_seurat)

We can convert SummarizedCellExperiment to Seurat object

seurat <- as.Seurat(test, counts = "counts", data = "logcounts")
# read in the Count matrix as a dataframe
matrix = read.csv("count_matrix_gastr.csv", row.names = 1, sep = ",")

# convert dataframe to matrix
matrix <- as.matrix(matrix)
# read in metadata
obs = read.csv("anndata_as_csvs/obs.csv")

# read in pca coordinates
obsm = read.csv("anndata_as_csvs/obsm.csv")

# genome informations
var = read.csv("anndata_as_csvs/var.csv")
var %>% head
##         X    gene          Accession Chromosome     End   Start Strand
## 1    Xkr4    Xkr4 ENSMUSG00000051951          1 3671498 3205901      -
## 2  Gm1992  Gm1992 ENSMUSG00000089699          1 3513553 3466587      +
## 3 Gm19938 Gm19938 ENSMUSG00000102331          1 3658904 3647309      -
## 4 Gm37381 Gm37381 ENSMUSG00000102343          1 3986215 3905739      -
## 5     Rp1     Rp1 ENSMUSG00000025900          1 4409241 3999557      -
## 6   Sox17   Sox17 ENSMUSG00000025902          1 4497354 4490931      -
##   highly_variable       means dispersions dispersions_norm        mean
## 1            True 0.367476906   1.3238081       2.54351380 0.204760066
## 2           False 0.006202907   0.1363408      -0.04272088 0.004248043
## 3           False 0.036352255   0.2382920       0.23294678 0.024285307
## 4           False 0.002336403   0.8813052       1.97160080 0.001403798
## 5            True 0.019664977   1.4180168       3.42282410 0.010390339
## 6            True 0.154462862   0.4595927       0.83132523 0.103584691
##          std
## 1 0.46847308
## 2 0.05438302
## 3 0.13469896
## 4 0.03449084
## 5 0.10144195
## 6 0.27630131

# pca coordinates
varm = read.csv("anndata_as_csvs/varm.csv")
# add cells and genes as row/column names respectively
colnames(matrix) <- var$gene
rownames(matrix) <- obs$cell

# Have a look at th ematrix
matrix[0:5, 0:5]

# conver to sparse matrix
matrix_sparse <- as(matrix, "sparseMatrix")
matrix_sparse[0:5, 0:5]
# we transpose the count matrix to genes x cells
#gastr_seurat <- CreateSeuratObject(counts = t(matrix_sparse), project = "mouse_gastrulation")
#saveRDS(gastr_seurat, "Seurat_rna_gastr/Seurat_object1")

gastr_seurat <- readRDS("Seurat_objects/rna_seurat1.rds")
# we can add the metadata columns to the seurat object
gastr_seurat <- AddMetaData(gastr_seurat, obs %>%
                              column_to_rownames("cell"))

gastr_seurat@meta.data %>% head
##                              orig.ident nCount_RNA nFeature_RNA    sample
## E7.5_rep1#AAACAGCCAAACTCAT-1       E7.5       7538         2929 E7.5_rep1
## E7.5_rep1#AAACAGCCACAACCTA-1       E7.5      12134         4125 E7.5_rep1
## E7.5_rep1#AAACAGCCATCCTGAA-1       E7.5       6033         2676 E7.5_rep1
## E7.5_rep1#AAACAGCCATGCTATG-1       E7.5      11992         3984 E7.5_rep1
## E7.5_rep1#AAACATGCAACCTGGT-1       E7.5      11571         3702 E7.5_rep1
## E7.5_rep1#AAACATGCAATGAATG-1       E7.5      10923         4029 E7.5_rep1
##                                         barcode stage mitochondrial_percent_RNA
## E7.5_rep1#AAACAGCCAAACTCAT-1 AAACAGCCAAACTCAT-1  E7.5                  16.10507
## E7.5_rep1#AAACAGCCACAACCTA-1 AAACAGCCACAACCTA-1  E7.5                  20.09230
## E7.5_rep1#AAACAGCCATCCTGAA-1 AAACAGCCATCCTGAA-1  E7.5                  21.63103
## E7.5_rep1#AAACAGCCATGCTATG-1 AAACAGCCATGCTATG-1  E7.5                  24.96664
## E7.5_rep1#AAACATGCAACCTGGT-1 AAACATGCAACCTGGT-1  E7.5                  14.47584
## E7.5_rep1#AAACATGCAATGAATG-1 AAACATGCAATGAATG-1  E7.5                  15.92969
##                              ribosomal_percent_RNA pass_rnaQC   celltype.mapped
## E7.5_rep1#AAACAGCCAAACTCAT-1             12.072168       True  Primitive_Streak
## E7.5_rep1#AAACAGCCACAACCTA-1              7.507829       True      ExE_ectoderm
## E7.5_rep1#AAACAGCCATCCTGAA-1              6.364993       True  Nascent_mesoderm
## E7.5_rep1#AAACAGCCATGCTATG-1              8.138759       True          Epiblast
## E7.5_rep1#AAACATGCAACCTGGT-1             12.730101       True Parietal_endoderm
## E7.5_rep1#AAACATGCAATGAATG-1              5.319052       True  Somitic_mesoderm
##                              celltype.score closest.cell hybrid_score
## E7.5_rep1#AAACAGCCAAACTCAT-1           0.76   cell_79749   0.18205486
## E7.5_rep1#AAACAGCCACAACCTA-1           1.00   cell_80539   0.03686339
## E7.5_rep1#AAACAGCCATCCTGAA-1           0.64   cell_82825   0.14067649
## E7.5_rep1#AAACAGCCATGCTATG-1           0.80   cell_84725   0.74835041
## E7.5_rep1#AAACATGCAACCTGGT-1           1.00    cell_4248   0.27021904
## E7.5_rep1#AAACATGCAATGAATG-1           0.76   cell_13439   0.30786430
##                              doublet_call TSSEnrichment_atac ReadsInTSS_atac
## E7.5_rep1#AAACAGCCAAACTCAT-1        False             12.369             406
## E7.5_rep1#AAACAGCCACAACCTA-1        False                 NA              NA
## E7.5_rep1#AAACAGCCATCCTGAA-1        False             10.097            1596
## E7.5_rep1#AAACAGCCATGCTATG-1        False              9.157            2770
## E7.5_rep1#AAACATGCAACCTGGT-1        False             17.397            1722
## E7.5_rep1#AAACATGCAATGAATG-1        False             16.820            2149
##                              PromoterRatio_atac NucleosomeRatio_atac
## E7.5_rep1#AAACAGCCAAACTCAT-1          0.2428083             2.442157
## E7.5_rep1#AAACAGCCACAACCTA-1                 NA                   NA
## E7.5_rep1#AAACAGCCATCCTGAA-1          0.1533246             1.437051
## E7.5_rep1#AAACAGCCATGCTATG-1          0.1664038             1.236268
## E7.5_rep1#AAACATGCAACCTGGT-1          0.2454128             2.435776
## E7.5_rep1#AAACATGCAATGAATG-1          0.2148524             2.196279
##                              nFrags_atac BlacklistRatio_atac pass_atacQC
## E7.5_rep1#AAACAGCCAAACTCAT-1        3511          0.07661635       False
## E7.5_rep1#AAACAGCCACAACCTA-1          NA                  NA       False
## E7.5_rep1#AAACAGCCATCCTGAA-1       22048          0.01317580        True
## E7.5_rep1#AAACAGCCATGCTATG-1       37415          0.01683817        True
## E7.5_rep1#AAACATGCAACCTGGT-1       13080          0.04510703        True
## E7.5_rep1#AAACATGCAATGAATG-1       19411          0.01542940        True
##                              celltype.predicted sample_batch
## E7.5_rep1#AAACAGCCAAACTCAT-1   Primitive_Streak E7.5_rep1#-1
## E7.5_rep1#AAACAGCCACAACCTA-1       ExE_ectoderm E7.5_rep1#-1
## E7.5_rep1#AAACAGCCATCCTGAA-1   Nascent_mesoderm E7.5_rep1#-1
## E7.5_rep1#AAACAGCCATGCTATG-1           Epiblast E7.5_rep1#-1
## E7.5_rep1#AAACATGCAACCTGGT-1  Parietal_endoderm E7.5_rep1#-1
## E7.5_rep1#AAACATGCAATGAATG-1   Somitic_mesoderm E7.5_rep1#-1
##                              initial_size_spliced initial_size_unspliced
## E7.5_rep1#AAACAGCCAAACTCAT-1                 6130                    637
## E7.5_rep1#AAACAGCCACAACCTA-1                 7147                   3678
## E7.5_rep1#AAACAGCCATCCTGAA-1                 3349                   2018
## E7.5_rep1#AAACAGCCATGCTATG-1                 7554                   3098
## E7.5_rep1#AAACATGCAACCTGGT-1                 7945                   2200
## E7.5_rep1#AAACATGCAATGAATG-1                 5340                   4177
##                              initial_size leiden
## E7.5_rep1#AAACAGCCAAACTCAT-1         6130      0
## E7.5_rep1#AAACAGCCACAACCTA-1         7147      1
## E7.5_rep1#AAACAGCCATCCTGAA-1         3349      6
## E7.5_rep1#AAACAGCCATGCTATG-1         7554      0
## E7.5_rep1#AAACATGCAACCTGGT-1         7945     26
## E7.5_rep1#AAACATGCAATGAATG-1         5340      6

QC

Empty Droplets


tibble(sample = gastr_seurat@meta.data$sample, umi_per_cell = colSums(gastr_seurat@assays$RNA@counts)) %>% 
  arrange(sample, desc(umi_per_cell)) %>% 
  group_by(sample) %>% 
  mutate(idx = seq_along(sample)) %>% 
  mutate(cum_umi_per_cell = cumsum(umi_per_cell)) %>% 
  ggplot() +
  geom_line(aes(x = idx, y = cum_umi_per_cell)) +
  facet_wrap(~sample, scales = "fixed") +
  scale_y_log10() + scale_x_log10() +
  ylab("cumulative UMI count") +
  xlab("index")

  • From the plots below it seems that all cells with percentage of mitochondrial genes above 50% were removed.
variables <- c("nFeature_RNA", "nCount_RNA", "mitochondrial_percent_RNA", "ribosomal_percent_RNA")
map(variables, function(n){
  df <- gastr_seurat@meta.data
  ggplot(df) +
    geom_boxplot(aes(x = df %>% pull("sample"), y = df %>% pull(n),
                     fill = df %>% pull("sample")), alpha = .1) +
    geom_violin(aes(x = df %>% pull("sample"), y = df %>% pull(n),
                     fill = df %>% pull("sample")), alpha = .5) +
    xlab("sample") +
    ylab(paste0(n)) +
    labs(title = paste0(n)) +
    guides(fill=guide_legend(title="sample"))
})
## [[1]]

## 
## [[2]]

## 
## [[3]]

## 
## [[4]]

How good are the annotations?

The annotations are similar across the different samples. However, there are some differences in the confidence with which cells can me mapped for different celltypes. For example, cardiomyocytes, erythroids and extraembryonic ectoderm and endoderm (but not mesoderm), mesenchyme and parietal endoderm can be mapped with very high confidence.

gastr_seurat@meta.data %>% 
  ggplot() + 
  geom_histogram(aes(x = celltype.score)) +
  facet_wrap(~sample, scales = "fixed") 

  #scale_y_log10() 

gastr_seurat@meta.data %>% 
  ggplot() + 
  geom_boxplot(aes(x = celltype.mapped, y = celltype.score, fill = celltype.mapped)) +
  theme(axis.text.x = element_text(angle = 90, vjust = 0.8, hjust=1)) + NoLegend()

Normalize & Scale

gastr_seurat <- gastr_seurat %>% 
  NormalizeData(verbose = FALSE) %>% 
  ScaleData(verbose = FALSE) %>%
  FindVariableFeatures(verbose = FALSE)


#gastr_seurat@assays$RNA@data[0:10, 0:10]

PCA

I will proceed with 15 PCs.

gastr_seurat <- RunPCA(gastr_seurat, features = VariableFeatures(gastr_seurat),
             verbose = FALSE)

ElbowPlot(gastr_seurat)

pca_plots <- comprehenr::to_list(for (i in 1:15)
  DimPlot(gastr_seurat, reduction = "pca", dims = i:(i+1)) +
    theme())

#pca_plots
#gridExtra::grid.arrange(unlist(pca_plots), ncol = 3, nrow = 5)

Clustering

gastr_seurat <- FindNeighbors(gastr_seurat, verbose = FALSE)
gastr_seurat <- FindClusters(gastr_seurat, verbose = FALSE, resolution = 0.9)
gastr_seurat <- RunUMAP(gastr_seurat, verbose = FALSE, dims = 1:15)
## Warning: The default method for RunUMAP has changed from calling Python UMAP via reticulate to the R-native UWOT using the cosine metric
## To use Python UMAP via reticulate, set umap.method to 'umap-learn' and metric to 'correlation'
## This message will be shown once per session

Visualization

colPalette_celltypes = c('#532C8A',
 '#c19f70',
 '#f9decf',
 '#c9a997',
 '#B51D8D',
 '#3F84AA',
 '#9e6762',
 '#354E23',
 '#F397C0',
 '#ff891c',
 '#635547',
 '#C72228',
 '#f79083',
 '#EF4E22',
 '#989898',
 '#7F6874',
 '#8870ad',
 '#647a4f',
 '#EF5A9D',
 '#FBBE92',
 '#139992',
 '#cc7818',
 '#DFCDE4',
 '#8EC792',
 '#C594BF',
 '#C3C388',
 '#0F4A9C',
 '#FACB12',
 '#8DB5CE',
 '#1A1A1A',
 '#C9EBFB',
 '#DABE99',
 '#65A83E',
 '#005579',
 '#CDE088',
 '#f7f79e',
 '#F6BFCB')
celltypes <- (gastr_seurat@meta.data %>% group_by(celltype.mapped) %>% 
  summarise(n = n()))$celltype.mapped

col <- setNames(colPalette_celltypes, celltypes)
DimPlot(gastr_seurat, reduction = "umap", pt.size = 1, 
        group.by = "celltype.mapped", label = TRUE, repel = TRUE, cols = col) +
  NoLegend()

DimPlot(gastr_seurat, reduction = "umap", pt.size = 1, 
        group.by = "celltype.mapped", cols = col) #, label = TRUE, repel = TRUE) +

DimPlot(gastr_seurat, reduction = "umap", pt.size = .1, 
        group.by = "seurat_clusters", label = TRUE) +
  NoLegend()

p1 <- DimPlot(gastr_seurat, reduction = "umap", pt.size = .1, group.by = "sample")

p2 <- FeaturePlot(gastr_seurat, reduction = "umap", pt.size = .1,
            features = "nCount_RNA") +
    scale_color_viridis_c() 
p3 <- FeaturePlot(gastr_seurat, reduction = "umap", pt.size = .1, features = "mitochondrial_percent_RNA") +
    scale_color_viridis_c() 

p4 <- FeaturePlot(gastr_seurat, reduction = "umap", pt.size = .1, features = "nFeature_RNA") +
    scale_color_viridis_c() 

gridExtra::grid.arrange(p1, p2, p3, p4, ncol = 2, nrow = 2)

DimPlot(gastr_seurat, reduction = "umap", pt.size = 1, 
        group.by = "celltype.mapped", split.by = "orig.ident", ncol = 1, cols = col)

gastr_seurat@meta.data %>%
  group_by(orig.ident, celltype.mapped) %>% 
  summarise(Total = n()) %>% 
  mutate(freq = Total/sum(Total)) %>% 
  ggplot(aes(x = celltype.mapped, y = freq, fill = orig.ident)) +
  geom_bar(position = "dodge", stat = "identity") +
  theme(axis.text.x = element_text(angle = 45, vjust = 0.8, hjust=1)) +
  facet_wrap(~orig.ident, ncol = 1)

We can see that nascent mesoderm, epiblast and primitive streak are only present at E75. Also, extraembryonice endoderm and ectoderm are highest and decrease with progressing gastrulation. Forebrain/Midbrain/Hindbrain, neural crest and neuromesodermal progenitor (NMP) cells are not present at E7.5, but emerge at E8.0 and are present at even higher percentage at E8.5. The same is true for Allantois, erythroids (produce red blood cells, remain in bone marrow)and cardiomyocytes.

(Pijuan_Sala et.al, A single-cell molecular map of mouse gastrulation and early organogenesis, 2019, Nature)


gastr_seurat@meta.data %>% ggplot() +
  geom_bar(aes(x = orig.ident, fill = celltype.mapped), alpha = .6)



# plot the frequency of each cell type at each embryonic stage
# all frequencies for one embryonic stage would add up to 0
gastr_seurat@meta.data %>%
  group_by(orig.ident, celltype.mapped) %>% 
  summarise(Total = n()) %>% 
  mutate(freq = Total/sum(Total)) %>% 
  ggplot(aes(x = celltype.mapped, y = freq, fill = orig.ident)) +
  geom_bar(position = "dodge", stat = "identity") +
  theme(axis.text.x = element_text(angle = 45, vjust = 0.8, hjust=1)) 

subset(gastr_seurat, subset = orig.ident == "E7.5")
## An object of class Seurat 
## 32245 features across 13068 samples within 1 assay 
## Active assay: RNA (32245 features, 2000 variable features)
##  2 dimensional reductions calculated: pca, umap
stages <- c("E7.5", "E8.0", "E8.5")
seurat_objects <- map(stages, function(n){
  gastr_subset <- subset(gastr_seurat, subset = orig.ident == n)
  gastr_subset <- gastr_subset  %>% 
    NormalizeData(verbose = FALSE) %>% 
    ScaleData(verbose = FALSE) %>%
    FindVariableFeatures(verbose = FALSE) 
  gastr_subset <- gastr_subset %>%  RunPCA(features = VariableFeatures(gastr_subset), verbose = FALSE) %>% 
    FindNeighbors(verbose = FALSE) %>% 
    FindClusters(verbose = FALSE, resolution = .9) %>% 
    RunUMAP(verbose = TRUE, dims = 1:15)
  list(name = n, object = gastr_subset)
    
})


e75 <- seurat_objects[[1]]$object
e80 <- seurat_objects[[2]]$object
e85 <- seurat_objects[[3]]$object
umaps <- comprehenr::to_list(for (i in 1:3)
  DimPlot(gastr_seurat, reduction = "pca", dims = i:(i+1)) +
    theme())
plots <- map(seq.int(1,3), function(n){
  object <- seurat_objects[[n]]$object
  p1 <- DimPlot(object, reduction = "umap", group.by = "celltype.mapped", 
                cols = col, size = .1) +
    labs(title = paste0(seurat_objects[[n]]$name, " celltypes"))
  list(plot = p1)
})

gridExtra::grid.arrange(plots[[1]]$p, plots[[2]]$p, plots[[3]]$p, ncol = 1)

scATAC-seq data

# read in atac anndata
atac_gastr <- readH5AD("anndata_atac.h5ad")
atac_gastr
## class: SingleCellExperiment 
## dim: 203484 38158 
## metadata(0):
## assays(1): X
## rownames(203484): chr1:3035578-3036178 chr1:3044896-3045496 ...
##   chrX:169925470-169926070 chrX:169935781-169936381
## rowData names(5): chr start end score idx
## colnames(38158): E8.5_rep1#GTGGATGCACTAGCGT-1
##   E8.5_rep1#CCGCTAGCATATTGAC-1 ... E8.0_rep2#CGCCTGTGTACTGAAT-1
##   E8.0_rep2#TTGTGAGGTTTAAAGC-1
## colData names(34): BlacklistRatio nDiFrags ... ReadsInPeaks FRIP
## reducedDimNames(0):
## mainExpName: NULL
## altExpNames(0):
# convert SingleCellExperiment to Seurat object
atac_seurat <- as.Seurat(atac_gastr, counts = "X", data = "X")
# adding metadata
atac_seurat <- AddMetaData(atac_seurat, metadata = as.data.frame(atac_gastr@colData))
# genome annotations from EnsDb
annotations <- GetGRangesFromEnsDb(ensdb = EnsDb.Mmusculus.v79)

# change to UCSC style 
seqlevelsStyle(annotations) <- "UCSC"

# add gene information to the seurat object
Annotation(atac_seurat) <- annotations

QC ATAC

atac_seurat@meta.data %>%
  ggplot() +
  geom_density2d_filled(aes(x=log10(nFrags_atac ), y=TSSEnrichment_atac), bins=20) +
  geom_hline(yintercept = 5, color="green", linetype="dashed") +
  geom_vline(xintercept = 3, color="green", linetype="dashed") +
  #geom_xsidedensity(aes(x=log10(pre_filter_meta$nFrags))) +
  #geom_ysidedensity(aes(y = pre_filter_meta$TSSEnrichment)) +
  facet_wrap(~sample) +
  theme(legend.position = "none") +
  labs(x = "Log10 Unique Fragments", y = "TSS Enrichment Score")

p1 <- atac_seurat@meta.data %>% 
  ggplot() +
  ggridges::geom_density_ridges(aes(x = TSSEnrichment, y = Sample, fill = Sample),
                                alpha = .6)

p2 <- atac_seurat@meta.data %>% 
  ggplot() +
  geom_violin(aes(x = Sample, y = TSSEnrichment, fill = Sample), alpha = 0.6) +
  geom_boxplot(aes(x = Sample, y = TSSEnrichment,fill = Sample), alpha = 0.1) + 
  theme(legend.position = "none") +
  labs(title = "TSS Enrichment")
cowplot::plot_grid(p2, p1, ncol = 2)

p1 <- atac_seurat@meta.data %>% 
  ggplot() +
  ggridges::geom_density_ridges(aes(x = nFrags_atac , y = Sample, fill = Sample),
                                alpha = .6)

p2 <- atac_seurat@meta.data %>% 
  ggplot() +
  geom_violin(aes(x = Sample, y = nFrags_atac , fill = Sample), alpha = 0.6) +
  geom_boxplot(aes(x = Sample, y = nFrags_atac ,fill = Sample), alpha = 0.1) + 
  theme(legend.position = "none") +
  labs(title = "TSS Enrichment")
cowplot::plot_grid(p2, p1, ncol = 2)

Normalization ATAC

Latent Semantic Indexing

  • TF-IDF normalization
    • normalizes across cells (sequencing depth)
    • across peak (higher values to more rare peaks)
  • Select Top features
  • Run SVD on selected features
atac_seurat_test <- RunTFIDF(atac_seurat)
atac_seurat_test <- FindTopFeatures(atac_seurat_test)
atac_seurat_test <- RunSVD(atac_seurat_test)

The first LSI component often captures sequencing depth. We will therefore remove it from downstream analysis. The correlation between sequencing depth and each LSI component is shown in the plot below.

DepthCor(atac_seurat_test)

Visualization

atac_seurat <- RunUMAP(atac_seurat_test, reduction = "lsi", dims = 2:30)
aatac_seurat <- FindNeighbors(atac_seurat, reduction = "lsi", dims = 2:30)

# for Clsutering instead of Louvian SLM algorithm is used
#atac_seurat <- FindClusters(atac_seurat, verbose = FALSE, algorithm = 3) 
DimPlot(atac_seurat, group.by = "celltype.mapped",  pt.size = 1, cols = col) +
  labs(title = "scATAC-seq Celltype")

DimPlot(gastr_seurat , group.by = "celltype.mapped", pt.size = 1, cols = col,
        reduction = "umap") +
  labs(title = "scRNA-seq Celltype")

atac_seurat@meta.data %>% 
  ggplot(aes(x = log10(nCount_originalexp ), y = log10(nFrags_atac))) +
  geom_point(alpha = .2, size = .2) +
  ggside::geom_xsidedensity() +
  ggside::geom_ysidedensity() +
  facet_wrap(~sample) +
  labs(x = "Log10 Counts", y = "log10 Unique Fragments")

atac_seurat@meta.data %>% 
  ggplot(aes(x = log10(nCount_originalexp), y = log10(TSSEnrichment))) +
  geom_point(size = .2, alpha = .2) +
  ggside::geom_xsidedensity() +
  ggside::geom_ysidedensity() +
  facet_wrap(~sample)

atac_seurat@meta.data %>% 
  ggplot() +
  geom_histogram(aes(x = PromoterRatio_atac)) 


atac_seurat@meta.data %>% 
  ggplot() +
  geom_histogram(aes(x = NucleosomeRatio_atac)) 

atac_seurat@meta.data %>% 
  mutate(col = case_when(
    PassQC  == 1 & pass_rnaQC  == TRUE~ "Both",
    PassQC  == 1 & pass_rnaQC == TRUE ~ "Only ATAC",
    PassQC  == 0 & pass_rnaQC == TRUE ~ "Only RNA",
    PassQC  == 0 & pass_rnaQC == TRUE ~ "None"
  )) %>% 
  ggplot(aes(x = log10(nCount_originalexp), y = log10(nFrags_atac))) +
    geom_point(aes(color = col), size = 0.4, alpha = 0.4) +
  scale_color_manual(values = c("Both" = "forestgreen",
                                "Only RNA" = "blue",
                                "Only ATAC" = "orange",
                                "None" = "grey")) 

Why does this plot look different when using the RNA-seq dataset?

gastr_seurat@meta.data %>% 
  mutate(col = case_when(
    pass_atacQC == "True" & pass_rnaQC  == "True" ~ "Both",
    pass_atacQC =="True" & pass_rnaQC == "False" ~ "Only ATAC",
    pass_atacQC =="False" & pass_rnaQC == "True" ~ "Only RNA",
    pass_atacQC =="False" & pass_rnaQC == "False" ~ "None"
  )) %>% 
  ggplot(aes(x = log10(nCount_RNA), y = log10(nFrags_atac))) +
    geom_point(aes(color = col), size = 0.4, alpha = 0.4) +
  scale_color_manual(values = c("Both" = "forestgreen",
                                "Only RNA" = "blue",
                                "Only ATAC" = "orange",
                                "None" = "grey")) 
## Warning: Removed 3210 rows containing missing values (geom_point).

gastr_seurat@meta.data %>% 
  dplyr::filter(pass_atacQC == "True") %>%
  mutate(col = case_when(
    pass_atacQC == "True" & pass_rnaQC  == "True" ~ "Both",
    pass_atacQC =="True" & pass_rnaQC == "False" ~ "Only ATAC",
    pass_atacQC =="False" & pass_rnaQC == "True" ~ "Only RNA",
    pass_atacQC =="False" & pass_rnaQC == "False" ~ "None"
  )) %>% 
  ggplot(aes(x = log10(nCount_RNA), y = log10(nFrags_atac))) +
    geom_point(aes(color = col), size = 0.4, alpha = 0.4) +
  scale_color_manual(values = c("Both" = "forestgreen",
                                "Only RNA" = "blue",
                                "Only ATAC" = "orange",
                                "None" = "grey")) 

Integrating RNA & ATAC

We will remove all cells from the scRNA-seq dataset which do not pass the scATAC-seq QC and vice versa.

#rna_seurat_filt <- subset(gastr_seurat, pass_atacQC == "True")
# atac_seurat_filt <- subset(atac_seurat, pass_rnaQC == TRUE)
LS0tCnRpdGxlOiAiZ2FzdHJ1bGF0aW9uX3JuYSIKb3V0cHV0OiAKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB0cnVlCiAgICB0b2NfZGVwdGg6IDUKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICB0aGVtZTogY29zbW8KICAgIGhpZ2hsaWdodDogdGV4dG1hdGUKLS0tCgoKPHN0eWxlPgpib2R5IHsKdGV4dC1hbGlnbjoganVzdGlmeX0KPC9zdHlsZT4KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoY2FjaGUgPSBGQUxTRSwgYXV0b2RlcCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgY29sbGFwc2UgPSBUUlVFLCBtZXNzYWdlID0gRkFMU0UpCmtuaXRyOjpvcHRzX2tuaXQkc2V0KHJvb3QuZGlyID0gIi9vbWljcy9ncm91cHMvT0UwNTMzL2ludGVybmFsL2thdGhhcmluYS9zY0RvUkkvZ2FzdHJ1bGF0aW9uX2RhdGEvIikKc2V0d2QoIi9vbWljcy9ncm91cHMvT0UwNTMzL2ludGVybmFsL2thdGhhcmluYS9zY0RvUkkvZ2FzdHJ1bGF0aW9uX2RhdGEvIikKCnNldC5zZWVkKDEpCmBgYAoKCiMjIExvYWQgbGlicmFyaWVzCiAgCmBgYHtyfQojbGlicmFyeShBcmNoUikKbGlicmFyeShrbml0cikKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoU2V1cmF0KQpsaWJyYXJ5KFNldXJhdERhdGEpCmxpYnJhcnkoc2NhdGVyKQpsaWJyYXJ5KHplbGxrb252ZXJ0ZXIpCmxpYnJhcnkoU2luZ2xlQ2VsbEV4cGVyaW1lbnQpCmxpYnJhcnkoRW5zRGIuTW11c2N1bHVzLnY3OSkKbGlicmFyeShTaWduYWMpCiNsaWJyYXJ5KFNldXJhdERpc2spCiNsaWJyYXJ5KGNhcmV0KQojaDVkaXNhYmxlRmlsZUxvY2tpbmcoKQpgYGAKCldlIGNhbiByZWFkIGluIHRoZSAuaDVhZCBmaWxlIGFzIGEgU3VtbWFyaXplZENlbGxFeHBlcmltZW50CgpgYGAKcm5hX2dhc3RyX1NFIDwtIHJlYWRINUFEKCJhbm5kYXRhX3JuYS5oNWFkIikKYGBgCgoKV2UgY2FuIGNvbnZlcnQgYSBTZXVyYXQgb2JqZWN0IHRvIGEgU3VtbWFyaXplZENlbGxFeHBlcmltZW50CgpgYGAKU0NFIDwtIGFzLlNpbmdsZUNlbGxFeHBlcmltZW50KGdhc3RyX3NldXJhdCkKYGBgCgpXZSBjYW4gY29udmVydCBTdW1tYXJpemVkQ2VsbEV4cGVyaW1lbnQgdG8gU2V1cmF0IG9iamVjdAoKYGBgCnNldXJhdCA8LSBhcy5TZXVyYXQodGVzdCwgY291bnRzID0gImNvdW50cyIsIGRhdGEgPSAibG9nY291bnRzIikKYGBgCgoKCmBgYCAKIyByZWFkIGluIHRoZSBDb3VudCBtYXRyaXggYXMgYSBkYXRhZnJhbWUKbWF0cml4ID0gcmVhZC5jc3YoImNvdW50X21hdHJpeF9nYXN0ci5jc3YiLCByb3cubmFtZXMgPSAxLCBzZXAgPSAiLCIpCgojIGNvbnZlcnQgZGF0YWZyYW1lIHRvIG1hdHJpeAptYXRyaXggPC0gYXMubWF0cml4KG1hdHJpeCkKYGBgCgpgYGB7cn0KIyByZWFkIGluIG1ldGFkYXRhCm9icyA9IHJlYWQuY3N2KCJhbm5kYXRhX2FzX2NzdnMvb2JzLmNzdiIpCgojIHJlYWQgaW4gcGNhIGNvb3JkaW5hdGVzCm9ic20gPSByZWFkLmNzdigiYW5uZGF0YV9hc19jc3ZzL29ic20uY3N2IikKCiMgZ2Vub21lIGluZm9ybWF0aW9ucwp2YXIgPSByZWFkLmNzdigiYW5uZGF0YV9hc19jc3ZzL3Zhci5jc3YiKQp2YXIgJT4lIGhlYWQKCiMgcGNhIGNvb3JkaW5hdGVzCnZhcm0gPSByZWFkLmNzdigiYW5uZGF0YV9hc19jc3ZzL3Zhcm0uY3N2IikKCmBgYAoKCgpgYGAKIyBhZGQgY2VsbHMgYW5kIGdlbmVzIGFzIHJvdy9jb2x1bW4gbmFtZXMgcmVzcGVjdGl2ZWx5CmNvbG5hbWVzKG1hdHJpeCkgPC0gdmFyJGdlbmUKcm93bmFtZXMobWF0cml4KSA8LSBvYnMkY2VsbAoKIyBIYXZlIGEgbG9vayBhdCB0aCBlbWF0cml4Cm1hdHJpeFswOjUsIDA6NV0KCiMgY29udmVyIHRvIHNwYXJzZSBtYXRyaXgKbWF0cml4X3NwYXJzZSA8LSBhcyhtYXRyaXgsICJzcGFyc2VNYXRyaXgiKQptYXRyaXhfc3BhcnNlWzA6NSwgMDo1XQpgYGAKCgpgYGB7cn0KIyB3ZSB0cmFuc3Bvc2UgdGhlIGNvdW50IG1hdHJpeCB0byBnZW5lcyB4IGNlbGxzCiNnYXN0cl9zZXVyYXQgPC0gQ3JlYXRlU2V1cmF0T2JqZWN0KGNvdW50cyA9IHQobWF0cml4X3NwYXJzZSksIHByb2plY3QgPSAibW91c2VfZ2FzdHJ1bGF0aW9uIikKI3NhdmVSRFMoZ2FzdHJfc2V1cmF0LCAiU2V1cmF0X3JuYV9nYXN0ci9TZXVyYXRfb2JqZWN0MSIpCgpnYXN0cl9zZXVyYXQgPC0gcmVhZFJEUygiU2V1cmF0X29iamVjdHMvcm5hX3NldXJhdDEucmRzIikKYGBgCgpgYGB7cn0KIyB3ZSBjYW4gYWRkIHRoZSBtZXRhZGF0YSBjb2x1bW5zIHRvIHRoZSBzZXVyYXQgb2JqZWN0Cmdhc3RyX3NldXJhdCA8LSBBZGRNZXRhRGF0YShnYXN0cl9zZXVyYXQsIG9icyAlPiUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sdW1uX3RvX3Jvd25hbWVzKCJjZWxsIikpCgpnYXN0cl9zZXVyYXRAbWV0YS5kYXRhICU+JSBoZWFkCmBgYAoKCiMgUUMKCgojIyMgRW1wdHkgRHJvcGxldHMKCmBgYHtyfQoKdGliYmxlKHNhbXBsZSA9IGdhc3RyX3NldXJhdEBtZXRhLmRhdGEkc2FtcGxlLCB1bWlfcGVyX2NlbGwgPSBjb2xTdW1zKGdhc3RyX3NldXJhdEBhc3NheXMkUk5BQGNvdW50cykpICU+JSAKICBhcnJhbmdlKHNhbXBsZSwgZGVzYyh1bWlfcGVyX2NlbGwpKSAlPiUgCiAgZ3JvdXBfYnkoc2FtcGxlKSAlPiUgCiAgbXV0YXRlKGlkeCA9IHNlcV9hbG9uZyhzYW1wbGUpKSAlPiUgCiAgbXV0YXRlKGN1bV91bWlfcGVyX2NlbGwgPSBjdW1zdW0odW1pX3Blcl9jZWxsKSkgJT4lIAogIGdncGxvdCgpICsKICBnZW9tX2xpbmUoYWVzKHggPSBpZHgsIHkgPSBjdW1fdW1pX3Blcl9jZWxsKSkgKwogIGZhY2V0X3dyYXAofnNhbXBsZSwgc2NhbGVzID0gImZpeGVkIikgKwogIHNjYWxlX3lfbG9nMTAoKSArIHNjYWxlX3hfbG9nMTAoKSArCiAgeWxhYigiY3VtdWxhdGl2ZSBVTUkgY291bnQiKSArCiAgeGxhYigiaW5kZXgiKQoKCmBgYAoKCgoqIEZyb20gdGhlIHBsb3RzIGJlbG93IGl0IHNlZW1zIHRoYXQgYWxsIGNlbGxzIHdpdGggcGVyY2VudGFnZSBvZiBtaXRvY2hvbmRyaWFsIApnZW5lcyBhYm92ZSA1MCUgd2VyZSByZW1vdmVkLgoqIAoKYGBge3J9CnZhcmlhYmxlcyA8LSBjKCJuRmVhdHVyZV9STkEiLCAibkNvdW50X1JOQSIsICJtaXRvY2hvbmRyaWFsX3BlcmNlbnRfUk5BIiwgInJpYm9zb21hbF9wZXJjZW50X1JOQSIpCm1hcCh2YXJpYWJsZXMsIGZ1bmN0aW9uKG4pewogIGRmIDwtIGdhc3RyX3NldXJhdEBtZXRhLmRhdGEKICBnZ3Bsb3QoZGYpICsKICAgIGdlb21fYm94cGxvdChhZXMoeCA9IGRmICU+JSBwdWxsKCJzYW1wbGUiKSwgeSA9IGRmICU+JSBwdWxsKG4pLAogICAgICAgICAgICAgICAgICAgICBmaWxsID0gZGYgJT4lIHB1bGwoInNhbXBsZSIpKSwgYWxwaGEgPSAuMSkgKwogICAgZ2VvbV92aW9saW4oYWVzKHggPSBkZiAlPiUgcHVsbCgic2FtcGxlIiksIHkgPSBkZiAlPiUgcHVsbChuKSwKICAgICAgICAgICAgICAgICAgICAgZmlsbCA9IGRmICU+JSBwdWxsKCJzYW1wbGUiKSksIGFscGhhID0gLjUpICsKICAgIHhsYWIoInNhbXBsZSIpICsKICAgIHlsYWIocGFzdGUwKG4pKSArCiAgICBsYWJzKHRpdGxlID0gcGFzdGUwKG4pKSArCiAgICBndWlkZXMoZmlsbD1ndWlkZV9sZWdlbmQodGl0bGU9InNhbXBsZSIpKQp9KQoKYGBgCgojIyBIb3cgZ29vZCBhcmUgdGhlIGFubm90YXRpb25zPwoKVGhlIGFubm90YXRpb25zIGFyZSBzaW1pbGFyIGFjcm9zcyB0aGUgZGlmZmVyZW50IHNhbXBsZXMuIEhvd2V2ZXIsIHRoZXJlIGFyZQpzb21lIGRpZmZlcmVuY2VzIGluIHRoZSBjb25maWRlbmNlIHdpdGggd2hpY2ggY2VsbHMgY2FuIG1lIG1hcHBlZCBmb3IgZGlmZmVyZW50CmNlbGx0eXBlcy4gRm9yIGV4YW1wbGUsIGNhcmRpb215b2N5dGVzLCBlcnl0aHJvaWRzIGFuZCBleHRyYWVtYnJ5b25pYyBlY3RvZGVybQphbmQgZW5kb2Rlcm0gKGJ1dCBub3QgbWVzb2Rlcm0pLCBtZXNlbmNoeW1lIGFuZCBwYXJpZXRhbCBlbmRvZGVybSBjYW4gYmUgbWFwcGVkCndpdGggdmVyeSBoaWdoIGNvbmZpZGVuY2UuCgpgYGB7ciwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9OH0KZ2FzdHJfc2V1cmF0QG1ldGEuZGF0YSAlPiUgCiAgZ2dwbG90KCkgKyAKICBnZW9tX2hpc3RvZ3JhbShhZXMoeCA9IGNlbGx0eXBlLnNjb3JlKSkgKwogIGZhY2V0X3dyYXAofnNhbXBsZSwgc2NhbGVzID0gImZpeGVkIikgCiAgI3NjYWxlX3lfbG9nMTAoKSAKCmdhc3RyX3NldXJhdEBtZXRhLmRhdGEgJT4lIAogIGdncGxvdCgpICsgCiAgZ2VvbV9ib3hwbG90KGFlcyh4ID0gY2VsbHR5cGUubWFwcGVkLCB5ID0gY2VsbHR5cGUuc2NvcmUsIGZpbGwgPSBjZWxsdHlwZS5tYXBwZWQpKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgdmp1c3QgPSAwLjgsIGhqdXN0PTEpKSArIE5vTGVnZW5kKCkKCgpgYGAKCgojIyBOb3JtYWxpemUgJiBTY2FsZQoKYGBge3J9Cmdhc3RyX3NldXJhdCA8LSBnYXN0cl9zZXVyYXQgJT4lIAogIE5vcm1hbGl6ZURhdGEodmVyYm9zZSA9IEZBTFNFKSAlPiUgCiAgU2NhbGVEYXRhKHZlcmJvc2UgPSBGQUxTRSkgJT4lCiAgRmluZFZhcmlhYmxlRmVhdHVyZXModmVyYm9zZSA9IEZBTFNFKQoKCiNnYXN0cl9zZXVyYXRAYXNzYXlzJFJOQUBkYXRhWzA6MTAsIDA6MTBdCmBgYAoKCiMjIyBQQ0EKCkkgd2lsbCBwcm9jZWVkIHdpdGggMTUgUENzLgoKYGBge3J9Cmdhc3RyX3NldXJhdCA8LSBSdW5QQ0EoZ2FzdHJfc2V1cmF0LCBmZWF0dXJlcyA9IFZhcmlhYmxlRmVhdHVyZXMoZ2FzdHJfc2V1cmF0KSwKICAgICAgICAgICAgIHZlcmJvc2UgPSBGQUxTRSkKCkVsYm93UGxvdChnYXN0cl9zZXVyYXQpCmBgYAoKYGBge3J9CnBjYV9wbG90cyA8LSBjb21wcmVoZW5yOjp0b19saXN0KGZvciAoaSBpbiAxOjE1KQogIERpbVBsb3QoZ2FzdHJfc2V1cmF0LCByZWR1Y3Rpb24gPSAicGNhIiwgZGltcyA9IGk6KGkrMSkpICsKICAgIHRoZW1lKCkpCgojcGNhX3Bsb3RzCiNncmlkRXh0cmE6OmdyaWQuYXJyYW5nZSh1bmxpc3QocGNhX3Bsb3RzKSwgbmNvbCA9IDMsIG5yb3cgPSA1KQoKYGBgCgojIyBDbHVzdGVyaW5nCgpgYGB7cn0KZ2FzdHJfc2V1cmF0IDwtIEZpbmROZWlnaGJvcnMoZ2FzdHJfc2V1cmF0LCB2ZXJib3NlID0gRkFMU0UpCmdhc3RyX3NldXJhdCA8LSBGaW5kQ2x1c3RlcnMoZ2FzdHJfc2V1cmF0LCB2ZXJib3NlID0gRkFMU0UsIHJlc29sdXRpb24gPSAwLjkpCmdhc3RyX3NldXJhdCA8LSBSdW5VTUFQKGdhc3RyX3NldXJhdCwgdmVyYm9zZSA9IEZBTFNFLCBkaW1zID0gMToxNSkKYGBgCgoKIyBWaXN1YWxpemF0aW9uCgpgYGB7cn0KY29sUGFsZXR0ZV9jZWxsdHlwZXMgPSBjKCcjNTMyQzhBJywKICcjYzE5ZjcwJywKICcjZjlkZWNmJywKICcjYzlhOTk3JywKICcjQjUxRDhEJywKICcjM0Y4NEFBJywKICcjOWU2NzYyJywKICcjMzU0RTIzJywKICcjRjM5N0MwJywKICcjZmY4OTFjJywKICcjNjM1NTQ3JywKICcjQzcyMjI4JywKICcjZjc5MDgzJywKICcjRUY0RTIyJywKICcjOTg5ODk4JywKICcjN0Y2ODc0JywKICcjODg3MGFkJywKICcjNjQ3YTRmJywKICcjRUY1QTlEJywKICcjRkJCRTkyJywKICcjMTM5OTkyJywKICcjY2M3ODE4JywKICcjREZDREU0JywKICcjOEVDNzkyJywKICcjQzU5NEJGJywKICcjQzNDMzg4JywKICcjMEY0QTlDJywKICcjRkFDQjEyJywKICcjOERCNUNFJywKICcjMUExQTFBJywKICcjQzlFQkZCJywKICcjREFCRTk5JywKICcjNjVBODNFJywKICcjMDA1NTc5JywKICcjQ0RFMDg4JywKICcjZjdmNzllJywKICcjRjZCRkNCJykKYGBgCgpgYGB7cn0KY2VsbHR5cGVzIDwtIChnYXN0cl9zZXVyYXRAbWV0YS5kYXRhICU+JSBncm91cF9ieShjZWxsdHlwZS5tYXBwZWQpICU+JSAKICBzdW1tYXJpc2UobiA9IG4oKSkpJGNlbGx0eXBlLm1hcHBlZAoKY29sIDwtIHNldE5hbWVzKGNvbFBhbGV0dGVfY2VsbHR5cGVzLCBjZWxsdHlwZXMpCmBgYAoKCmBgYHtyLCBmaWcud2lkdGg9MTUsIGZpZy5oZWlnaHQgPSAxMH0KRGltUGxvdChnYXN0cl9zZXVyYXQsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgcHQuc2l6ZSA9IDEsIAogICAgICAgIGdyb3VwLmJ5ID0gImNlbGx0eXBlLm1hcHBlZCIsIGxhYmVsID0gVFJVRSwgcmVwZWwgPSBUUlVFLCBjb2xzID0gY29sKSArCiAgTm9MZWdlbmQoKQpgYGAKCgpgYGB7ciwgZmlnLndpZHRoPTE1fQpEaW1QbG90KGdhc3RyX3NldXJhdCwgcmVkdWN0aW9uID0gInVtYXAiLCBwdC5zaXplID0gMSwgCiAgICAgICAgZ3JvdXAuYnkgPSAiY2VsbHR5cGUubWFwcGVkIiwgY29scyA9IGNvbCkgIywgbGFiZWwgPSBUUlVFLCByZXBlbCA9IFRSVUUpICsKYGBgCgpgYGB7cn0KRGltUGxvdChnYXN0cl9zZXVyYXQsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgcHQuc2l6ZSA9IC4xLCAKICAgICAgICBncm91cC5ieSA9ICJzZXVyYXRfY2x1c3RlcnMiLCBsYWJlbCA9IFRSVUUpICsKICBOb0xlZ2VuZCgpCmBgYAoKYGBge3IsIGZpZy53aWR0aD0xNSwgZmlnLmhlaWdodD04fQpwMSA8LSBEaW1QbG90KGdhc3RyX3NldXJhdCwgcmVkdWN0aW9uID0gInVtYXAiLCBwdC5zaXplID0gLjEsIGdyb3VwLmJ5ID0gInNhbXBsZSIpCgpwMiA8LSBGZWF0dXJlUGxvdChnYXN0cl9zZXVyYXQsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgcHQuc2l6ZSA9IC4xLAogICAgICAgICAgICBmZWF0dXJlcyA9ICJuQ291bnRfUk5BIikgKwogICAgc2NhbGVfY29sb3JfdmlyaWRpc19jKCkgCnAzIDwtIEZlYXR1cmVQbG90KGdhc3RyX3NldXJhdCwgcmVkdWN0aW9uID0gInVtYXAiLCBwdC5zaXplID0gLjEsIGZlYXR1cmVzID0gIm1pdG9jaG9uZHJpYWxfcGVyY2VudF9STkEiKSArCiAgICBzY2FsZV9jb2xvcl92aXJpZGlzX2MoKSAKCnA0IDwtIEZlYXR1cmVQbG90KGdhc3RyX3NldXJhdCwgcmVkdWN0aW9uID0gInVtYXAiLCBwdC5zaXplID0gLjEsIGZlYXR1cmVzID0gIm5GZWF0dXJlX1JOQSIpICsKICAgIHNjYWxlX2NvbG9yX3ZpcmlkaXNfYygpIAoKZ3JpZEV4dHJhOjpncmlkLmFycmFuZ2UocDEsIHAyLCBwMywgcDQsIG5jb2wgPSAyLCBucm93ID0gMikKYGBgCgoKYGBge3IsIGZpZy53aWR0aD0xNSwgZmlnLmhlaWdodD0xNX0KRGltUGxvdChnYXN0cl9zZXVyYXQsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgcHQuc2l6ZSA9IDEsIAogICAgICAgIGdyb3VwLmJ5ID0gImNlbGx0eXBlLm1hcHBlZCIsIHNwbGl0LmJ5ID0gIm9yaWcuaWRlbnQiLCBuY29sID0gMSwgY29scyA9IGNvbCkKYGBgCgoKCmBgYHtyLCBmaWcud2lkdGggPSAxMiwgZmlnLmhlaWdodD04fQpnYXN0cl9zZXVyYXRAbWV0YS5kYXRhICU+JQogIGdyb3VwX2J5KG9yaWcuaWRlbnQsIGNlbGx0eXBlLm1hcHBlZCkgJT4lIAogIHN1bW1hcmlzZShUb3RhbCA9IG4oKSkgJT4lIAogIG11dGF0ZShmcmVxID0gVG90YWwvc3VtKFRvdGFsKSkgJT4lIAogIGdncGxvdChhZXMoeCA9IGNlbGx0eXBlLm1hcHBlZCwgeSA9IGZyZXEsIGZpbGwgPSBvcmlnLmlkZW50KSkgKwogIGdlb21fYmFyKHBvc2l0aW9uID0gImRvZGdlIiwgc3RhdCA9ICJpZGVudGl0eSIpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCB2anVzdCA9IDAuOCwgaGp1c3Q9MSkpICsKICBmYWNldF93cmFwKH5vcmlnLmlkZW50LCBuY29sID0gMSkKYGBgCgpXZSBjYW4gc2VlIHRoYXQgbmFzY2VudCBtZXNvZGVybSwgZXBpYmxhc3QgYW5kIHByaW1pdGl2ZSBzdHJlYWsgYXJlIG9ubHkgcHJlc2VudCAKYXQgRTc1LiBBbHNvLCBleHRyYWVtYnJ5b25pY2UgZW5kb2Rlcm0gYW5kIGVjdG9kZXJtIGFyZSBoaWdoZXN0IGFuZCBkZWNyZWFzZSAKd2l0aCBwcm9ncmVzc2luZyBnYXN0cnVsYXRpb24uIEZvcmVicmFpbi9NaWRicmFpbi9IaW5kYnJhaW4sIG5ldXJhbCBjcmVzdCBhbmQgCm5ldXJvbWVzb2Rlcm1hbCBwcm9nZW5pdG9yIChOTVApIGNlbGxzIGFyZSBub3QgcHJlc2VudCBhdCAKRTcuNSwgYnV0IGVtZXJnZSBhdCBFOC4wIGFuZCBhcmUgcHJlc2VudCBhdCBldmVuIGhpZ2hlciBwZXJjZW50YWdlIGF0IEU4LjUuIFRoZSAKc2FtZSBpcyB0cnVlIGZvciBBbGxhbnRvaXMsIGVyeXRocm9pZHMgKHByb2R1Y2UgcmVkIGJsb29kIGNlbGxzLCByZW1haW4gaW4gYm9uZQptYXJyb3cpYW5kIGNhcmRpb215b2N5dGVzLgoKKFBpanVhbl9TYWxhIGV0LmFsLCBBIHNpbmdsZS1jZWxsIG1vbGVjdWxhciBtYXAgb2YgbW91c2UKZ2FzdHJ1bGF0aW9uIGFuZCBlYXJseSBvcmdhbm9nZW5lc2lzLCAyMDE5LCBOYXR1cmUpCgpgYGB7ciwgZmlnLndpZHRoPTEwfQoKZ2FzdHJfc2V1cmF0QG1ldGEuZGF0YSAlPiUgZ2dwbG90KCkgKwogIGdlb21fYmFyKGFlcyh4ID0gb3JpZy5pZGVudCwgZmlsbCA9IGNlbGx0eXBlLm1hcHBlZCksIGFscGhhID0gLjYpCgoKIyBwbG90IHRoZSBmcmVxdWVuY3kgb2YgZWFjaCBjZWxsIHR5cGUgYXQgZWFjaCBlbWJyeW9uaWMgc3RhZ2UKIyBhbGwgZnJlcXVlbmNpZXMgZm9yIG9uZSBlbWJyeW9uaWMgc3RhZ2Ugd291bGQgYWRkIHVwIHRvIDAKZ2FzdHJfc2V1cmF0QG1ldGEuZGF0YSAlPiUKICBncm91cF9ieShvcmlnLmlkZW50LCBjZWxsdHlwZS5tYXBwZWQpICU+JSAKICBzdW1tYXJpc2UoVG90YWwgPSBuKCkpICU+JSAKICBtdXRhdGUoZnJlcSA9IFRvdGFsL3N1bShUb3RhbCkpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBjZWxsdHlwZS5tYXBwZWQsIHkgPSBmcmVxLCBmaWxsID0gb3JpZy5pZGVudCkpICsKICBnZW9tX2Jhcihwb3NpdGlvbiA9ICJkb2RnZSIsIHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgdmp1c3QgPSAwLjgsIGhqdXN0PTEpKSAKICAKYGBgCgoKCmBgYHtyfQpzdWJzZXQoZ2FzdHJfc2V1cmF0LCBzdWJzZXQgPSBvcmlnLmlkZW50ID09ICJFNy41IikKYGBgCgoKYGBge3J9CnN0YWdlcyA8LSBjKCJFNy41IiwgIkU4LjAiLCAiRTguNSIpCnNldXJhdF9vYmplY3RzIDwtIG1hcChzdGFnZXMsIGZ1bmN0aW9uKG4pewogIGdhc3RyX3N1YnNldCA8LSBzdWJzZXQoZ2FzdHJfc2V1cmF0LCBzdWJzZXQgPSBvcmlnLmlkZW50ID09IG4pCiAgZ2FzdHJfc3Vic2V0IDwtIGdhc3RyX3N1YnNldCAgJT4lIAogICAgTm9ybWFsaXplRGF0YSh2ZXJib3NlID0gRkFMU0UpICU+JSAKICAgIFNjYWxlRGF0YSh2ZXJib3NlID0gRkFMU0UpICU+JQogICAgRmluZFZhcmlhYmxlRmVhdHVyZXModmVyYm9zZSA9IEZBTFNFKSAKICBnYXN0cl9zdWJzZXQgPC0gZ2FzdHJfc3Vic2V0ICU+JSAgUnVuUENBKGZlYXR1cmVzID0gVmFyaWFibGVGZWF0dXJlcyhnYXN0cl9zdWJzZXQpLCB2ZXJib3NlID0gRkFMU0UpICU+JSAKICAgIEZpbmROZWlnaGJvcnModmVyYm9zZSA9IEZBTFNFKSAlPiUgCiAgICBGaW5kQ2x1c3RlcnModmVyYm9zZSA9IEZBTFNFLCByZXNvbHV0aW9uID0gLjkpICU+JSAKICAgIFJ1blVNQVAodmVyYm9zZSA9IFRSVUUsIGRpbXMgPSAxOjE1KQogIGxpc3QobmFtZSA9IG4sIG9iamVjdCA9IGdhc3RyX3N1YnNldCkKICAgIAp9KQoKCmU3NSA8LSBzZXVyYXRfb2JqZWN0c1tbMV1dJG9iamVjdAplODAgPC0gc2V1cmF0X29iamVjdHNbWzJdXSRvYmplY3QKZTg1IDwtIHNldXJhdF9vYmplY3RzW1szXV0kb2JqZWN0CmBgYAoKCmBgYHtyfQp1bWFwcyA8LSBjb21wcmVoZW5yOjp0b19saXN0KGZvciAoaSBpbiAxOjMpCiAgRGltUGxvdChnYXN0cl9zZXVyYXQsIHJlZHVjdGlvbiA9ICJwY2EiLCBkaW1zID0gaTooaSsxKSkgKwogICAgdGhlbWUoKSkKYGBgCgoKYGBge3IsIGZpZy53aWR0aD0xNSwgZmlnLmhlaWdodD0yMH0KcGxvdHMgPC0gbWFwKHNlcS5pbnQoMSwzKSwgZnVuY3Rpb24obil7CiAgb2JqZWN0IDwtIHNldXJhdF9vYmplY3RzW1tuXV0kb2JqZWN0CiAgcDEgPC0gRGltUGxvdChvYmplY3QsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZ3JvdXAuYnkgPSAiY2VsbHR5cGUubWFwcGVkIiwgCiAgICAgICAgICAgICAgICBjb2xzID0gY29sLCBzaXplID0gLjEpICsKICAgIGxhYnModGl0bGUgPSBwYXN0ZTAoc2V1cmF0X29iamVjdHNbW25dXSRuYW1lLCAiIGNlbGx0eXBlcyIpKQogIGxpc3QocGxvdCA9IHAxKQp9KQoKZ3JpZEV4dHJhOjpncmlkLmFycmFuZ2UocGxvdHNbWzFdXSRwLCBwbG90c1tbMl1dJHAsIHBsb3RzW1szXV0kcCwgbmNvbCA9IDEpCmBgYAoKCiMgc2NBVEFDLXNlcSBkYXRhCgpgYGB7cn0KIyByZWFkIGluIGF0YWMgYW5uZGF0YQphdGFjX2dhc3RyIDwtIHJlYWRINUFEKCJhbm5kYXRhX2F0YWMuaDVhZCIpCmF0YWNfZ2FzdHIKYGBgCgoKCmBgYHtyfQojIGNvbnZlcnQgU2luZ2xlQ2VsbEV4cGVyaW1lbnQgdG8gU2V1cmF0IG9iamVjdAphdGFjX3NldXJhdCA8LSBhcy5TZXVyYXQoYXRhY19nYXN0ciwgY291bnRzID0gIlgiLCBkYXRhID0gIlgiKQpgYGAKCgpgYGB7cn0gCiMgYWRkaW5nIG1ldGFkYXRhCmF0YWNfc2V1cmF0IDwtIEFkZE1ldGFEYXRhKGF0YWNfc2V1cmF0LCBtZXRhZGF0YSA9IGFzLmRhdGEuZnJhbWUoYXRhY19nYXN0ckBjb2xEYXRhKSkKYGBgCgoKCmBgYAojIGdlbm9tZSBhbm5vdGF0aW9ucyBmcm9tIEVuc0RiCmFubm90YXRpb25zIDwtIEdldEdSYW5nZXNGcm9tRW5zRGIoZW5zZGIgPSBFbnNEYi5NbXVzY3VsdXMudjc5KQoKIyBjaGFuZ2UgdG8gVUNTQyBzdHlsZSAKc2VxbGV2ZWxzU3R5bGUoYW5ub3RhdGlvbnMpIDwtICJVQ1NDIgoKIyBhZGQgZ2VuZSBpbmZvcm1hdGlvbiB0byB0aGUgc2V1cmF0IG9iamVjdApBbm5vdGF0aW9uKGF0YWNfc2V1cmF0KSA8LSBhbm5vdGF0aW9ucwpgYGAKCgojIFFDIEFUQUMKCmBgYHtyfQphdGFjX3NldXJhdEBtZXRhLmRhdGEgJT4lCiAgZ2dwbG90KCkgKwogIGdlb21fZGVuc2l0eTJkX2ZpbGxlZChhZXMoeD1sb2cxMChuRnJhZ3NfYXRhYyApLCB5PVRTU0VucmljaG1lbnRfYXRhYyksIGJpbnM9MjApICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSA1LCBjb2xvcj0iZ3JlZW4iLCBsaW5ldHlwZT0iZGFzaGVkIikgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDMsIGNvbG9yPSJncmVlbiIsIGxpbmV0eXBlPSJkYXNoZWQiKSArCiAgI2dlb21feHNpZGVkZW5zaXR5KGFlcyh4PWxvZzEwKHByZV9maWx0ZXJfbWV0YSRuRnJhZ3MpKSkgKwogICNnZW9tX3lzaWRlZGVuc2l0eShhZXMoeSA9IHByZV9maWx0ZXJfbWV0YSRUU1NFbnJpY2htZW50KSkgKwogIGZhY2V0X3dyYXAofnNhbXBsZSkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogIGxhYnMoeCA9ICJMb2cxMCBVbmlxdWUgRnJhZ21lbnRzIiwgeSA9ICJUU1MgRW5yaWNobWVudCBTY29yZSIpCmBgYAoKCgpgYGB7ciwgZmlnLndpZHRoPTEwfQpwMSA8LSBhdGFjX3NldXJhdEBtZXRhLmRhdGEgJT4lIAogIGdncGxvdCgpICsKICBnZ3JpZGdlczo6Z2VvbV9kZW5zaXR5X3JpZGdlcyhhZXMoeCA9IFRTU0VucmljaG1lbnQsIHkgPSBTYW1wbGUsIGZpbGwgPSBTYW1wbGUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFscGhhID0gLjYpCgpwMiA8LSBhdGFjX3NldXJhdEBtZXRhLmRhdGEgJT4lIAogIGdncGxvdCgpICsKICBnZW9tX3Zpb2xpbihhZXMoeCA9IFNhbXBsZSwgeSA9IFRTU0VucmljaG1lbnQsIGZpbGwgPSBTYW1wbGUpLCBhbHBoYSA9IDAuNikgKwogIGdlb21fYm94cGxvdChhZXMoeCA9IFNhbXBsZSwgeSA9IFRTU0VucmljaG1lbnQsZmlsbCA9IFNhbXBsZSksIGFscGhhID0gMC4xKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogIGxhYnModGl0bGUgPSAiVFNTIEVucmljaG1lbnQiKQpjb3dwbG90OjpwbG90X2dyaWQocDIsIHAxLCBuY29sID0gMikKCmBgYAoKYGBge3IsIGZpZy53aWR0aD0xMH0KcDEgPC0gYXRhY19zZXVyYXRAbWV0YS5kYXRhICU+JSAKICBnZ3Bsb3QoKSArCiAgZ2dyaWRnZXM6Omdlb21fZGVuc2l0eV9yaWRnZXMoYWVzKHggPSBuRnJhZ3NfYXRhYyAsIHkgPSBTYW1wbGUsIGZpbGwgPSBTYW1wbGUpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFscGhhID0gLjYpCgpwMiA8LSBhdGFjX3NldXJhdEBtZXRhLmRhdGEgJT4lIAogIGdncGxvdCgpICsKICBnZW9tX3Zpb2xpbihhZXMoeCA9IFNhbXBsZSwgeSA9IG5GcmFnc19hdGFjICwgZmlsbCA9IFNhbXBsZSksIGFscGhhID0gMC42KSArCiAgZ2VvbV9ib3hwbG90KGFlcyh4ID0gU2FtcGxlLCB5ID0gbkZyYWdzX2F0YWMgLGZpbGwgPSBTYW1wbGUpLCBhbHBoYSA9IDAuMSkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpICsKICBsYWJzKHRpdGxlID0gIlRTUyBFbnJpY2htZW50IikKY293cGxvdDo6cGxvdF9ncmlkKHAyLCBwMSwgbmNvbCA9IDIpCmBgYAoKIyBOb3JtYWxpemF0aW9uIEFUQUMKCioqTGF0ZW50IFNlbWFudGljIEluZGV4aW5nKioKCiogVEYtSURGIG5vcm1hbGl6YXRpb24KICArIG5vcm1hbGl6ZXMgYWNyb3NzIGNlbGxzIChzZXF1ZW5jaW5nIGRlcHRoKQogICsgYWNyb3NzIHBlYWsgKGhpZ2hlciB2YWx1ZXMgdG8gbW9yZSByYXJlIHBlYWtzKQoqIFNlbGVjdCBUb3AgZmVhdHVyZXMKKiBSdW4gU1ZEIG9uIHNlbGVjdGVkIGZlYXR1cmVzCgpgYGB7cn0KYXRhY19zZXVyYXRfdGVzdCA8LSBSdW5URklERihhdGFjX3NldXJhdCkKYXRhY19zZXVyYXRfdGVzdCA8LSBGaW5kVG9wRmVhdHVyZXMoYXRhY19zZXVyYXRfdGVzdCkKYXRhY19zZXVyYXRfdGVzdCA8LSBSdW5TVkQoYXRhY19zZXVyYXRfdGVzdCkKYGBgClRoZSBmaXJzdCBMU0kgY29tcG9uZW50IG9mdGVuIGNhcHR1cmVzIHNlcXVlbmNpbmcgZGVwdGguIFdlIHdpbGwKdGhlcmVmb3JlIHJlbW92ZSBpdCBmcm9tIGRvd25zdHJlYW0gYW5hbHlzaXMuIFRoZSBjb3JyZWxhdGlvbiBiZXR3ZWVuIHNlcXVlbmNpbmcKZGVwdGggYW5kIGVhY2ggTFNJIGNvbXBvbmVudCBpcyBzaG93biBpbiB0aGUgcGxvdCBiZWxvdy4KCmBgYHtyfQpEZXB0aENvcihhdGFjX3NldXJhdF90ZXN0KQpgYGAKCiMgVmlzdWFsaXphdGlvbgoKYGBge3J9CmF0YWNfc2V1cmF0IDwtIFJ1blVNQVAoYXRhY19zZXVyYXRfdGVzdCwgcmVkdWN0aW9uID0gImxzaSIsIGRpbXMgPSAyOjMwKQphYXRhY19zZXVyYXQgPC0gRmluZE5laWdoYm9ycyhhdGFjX3NldXJhdCwgcmVkdWN0aW9uID0gImxzaSIsIGRpbXMgPSAyOjMwKQoKIyBmb3IgQ2xzdXRlcmluZyBpbnN0ZWFkIG9mIExvdXZpYW4gU0xNIGFsZ29yaXRobSBpcyB1c2VkCiNhdGFjX3NldXJhdCA8LSBGaW5kQ2x1c3RlcnMoYXRhY19zZXVyYXQsIHZlcmJvc2UgPSBGQUxTRSwgYWxnb3JpdGhtID0gMykgCmBgYAoKCgpgYGB7ciwgZmlnLndpZHRoID0gMTUsIGZpZy5oZWlnaHQ9MTB9CkRpbVBsb3QoYXRhY19zZXVyYXQsIGdyb3VwLmJ5ID0gImNlbGx0eXBlLm1hcHBlZCIsICBwdC5zaXplID0gMSwgY29scyA9IGNvbCkgKwogIGxhYnModGl0bGUgPSAic2NBVEFDLXNlcSBDZWxsdHlwZSIpCmBgYAoKYGBge3IsIGZpZy53aWR0aD0xNSwgZmlnLmhlaWdodD0xMH0KRGltUGxvdChnYXN0cl9zZXVyYXQgLCBncm91cC5ieSA9ICJjZWxsdHlwZS5tYXBwZWQiLCBwdC5zaXplID0gMSwgY29scyA9IGNvbCwKICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIpICsKICBsYWJzKHRpdGxlID0gInNjUk5BLXNlcSBDZWxsdHlwZSIpCgpgYGAKCgoKCgpgYGB7ciwgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTh9CmF0YWNfc2V1cmF0QG1ldGEuZGF0YSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gbG9nMTAobkNvdW50X29yaWdpbmFsZXhwICksIHkgPSBsb2cxMChuRnJhZ3NfYXRhYykpKSArCiAgZ2VvbV9wb2ludChhbHBoYSA9IC4yLCBzaXplID0gLjIpICsKICBnZ3NpZGU6Omdlb21feHNpZGVkZW5zaXR5KCkgKwogIGdnc2lkZTo6Z2VvbV95c2lkZWRlbnNpdHkoKSArCiAgZmFjZXRfd3JhcCh+c2FtcGxlKSArCiAgbGFicyh4ID0gIkxvZzEwIENvdW50cyIsIHkgPSAibG9nMTAgVW5pcXVlIEZyYWdtZW50cyIpCmBgYAoKCmBgYHtyLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9MTB9CmF0YWNfc2V1cmF0QG1ldGEuZGF0YSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gbG9nMTAobkNvdW50X29yaWdpbmFsZXhwKSwgeSA9IGxvZzEwKFRTU0VucmljaG1lbnQpKSkgKwogIGdlb21fcG9pbnQoc2l6ZSA9IC4yLCBhbHBoYSA9IC4yKSArCiAgZ2dzaWRlOjpnZW9tX3hzaWRlZGVuc2l0eSgpICsKICBnZ3NpZGU6Omdlb21feXNpZGVkZW5zaXR5KCkgKwogIGZhY2V0X3dyYXAofnNhbXBsZSkKYGBgCgoKYGBge3J9CmF0YWNfc2V1cmF0QG1ldGEuZGF0YSAlPiUgCiAgZ2dwbG90KCkgKwogIGdlb21faGlzdG9ncmFtKGFlcyh4ID0gUHJvbW90ZXJSYXRpb19hdGFjKSkgCgphdGFjX3NldXJhdEBtZXRhLmRhdGEgJT4lIAogIGdncGxvdCgpICsKICBnZW9tX2hpc3RvZ3JhbShhZXMoeCA9IE51Y2xlb3NvbWVSYXRpb19hdGFjKSkgCmBgYAoKCmBgYHtyfQphdGFjX3NldXJhdEBtZXRhLmRhdGEgJT4lIAogIG11dGF0ZShjb2wgPSBjYXNlX3doZW4oCiAgICBQYXNzUUMgID09IDEgJiBwYXNzX3JuYVFDICA9PSBUUlVFfiAiQm90aCIsCiAgICBQYXNzUUMgID09IDEgJiBwYXNzX3JuYVFDID09IFRSVUUgfiAiT25seSBBVEFDIiwKICAgIFBhc3NRQyAgPT0gMCAmIHBhc3Nfcm5hUUMgPT0gVFJVRSB+ICJPbmx5IFJOQSIsCiAgICBQYXNzUUMgID09IDAgJiBwYXNzX3JuYVFDID09IFRSVUUgfiAiTm9uZSIKICApKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gbG9nMTAobkNvdW50X29yaWdpbmFsZXhwKSwgeSA9IGxvZzEwKG5GcmFnc19hdGFjKSkpICsKICAgIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gY29sKSwgc2l6ZSA9IDAuNCwgYWxwaGEgPSAwLjQpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiQm90aCIgPSAiZm9yZXN0Z3JlZW4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJPbmx5IFJOQSIgPSAiYmx1ZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk9ubHkgQVRBQyIgPSAib3JhbmdlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTm9uZSIgPSAiZ3JleSIpKSAKYGBgCgoKV2h5IGRvZXMgdGhpcyBwbG90IGxvb2sgZGlmZmVyZW50IHdoZW4gdXNpbmcgdGhlIFJOQS1zZXEgZGF0YXNldD8KCmBgYHtyfQpnYXN0cl9zZXVyYXRAbWV0YS5kYXRhICU+JSAKICBtdXRhdGUoY29sID0gY2FzZV93aGVuKAogICAgcGFzc19hdGFjUUMgPT0gIlRydWUiICYgcGFzc19ybmFRQyAgPT0gIlRydWUiIH4gIkJvdGgiLAogICAgcGFzc19hdGFjUUMgPT0iVHJ1ZSIgJiBwYXNzX3JuYVFDID09ICJGYWxzZSIgfiAiT25seSBBVEFDIiwKICAgIHBhc3NfYXRhY1FDID09IkZhbHNlIiAmIHBhc3Nfcm5hUUMgPT0gIlRydWUiIH4gIk9ubHkgUk5BIiwKICAgIHBhc3NfYXRhY1FDID09IkZhbHNlIiAmIHBhc3Nfcm5hUUMgPT0gIkZhbHNlIiB+ICJOb25lIgogICkpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBsb2cxMChuQ291bnRfUk5BKSwgeSA9IGxvZzEwKG5GcmFnc19hdGFjKSkpICsKICAgIGdlb21fcG9pbnQoYWVzKGNvbG9yID0gY29sKSwgc2l6ZSA9IDAuNCwgYWxwaGEgPSAwLjQpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiQm90aCIgPSAiZm9yZXN0Z3JlZW4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJPbmx5IFJOQSIgPSAiYmx1ZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk9ubHkgQVRBQyIgPSAib3JhbmdlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTm9uZSIgPSAiZ3JleSIpKSAKYGBgCgoKCgpgYGB7cn0KZ2FzdHJfc2V1cmF0QG1ldGEuZGF0YSAlPiUgCiAgZHBseXI6OmZpbHRlcihwYXNzX2F0YWNRQyA9PSAiVHJ1ZSIpICU+JQogIG11dGF0ZShjb2wgPSBjYXNlX3doZW4oCiAgICBwYXNzX2F0YWNRQyA9PSAiVHJ1ZSIgJiBwYXNzX3JuYVFDICA9PSAiVHJ1ZSIgfiAiQm90aCIsCiAgICBwYXNzX2F0YWNRQyA9PSJUcnVlIiAmIHBhc3Nfcm5hUUMgPT0gIkZhbHNlIiB+ICJPbmx5IEFUQUMiLAogICAgcGFzc19hdGFjUUMgPT0iRmFsc2UiICYgcGFzc19ybmFRQyA9PSAiVHJ1ZSIgfiAiT25seSBSTkEiLAogICAgcGFzc19hdGFjUUMgPT0iRmFsc2UiICYgcGFzc19ybmFRQyA9PSAiRmFsc2UiIH4gIk5vbmUiCiAgKSkgJT4lIAogIGdncGxvdChhZXMoeCA9IGxvZzEwKG5Db3VudF9STkEpLCB5ID0gbG9nMTAobkZyYWdzX2F0YWMpKSkgKwogICAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBjb2wpLCBzaXplID0gMC40LCBhbHBoYSA9IDAuNCkgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJCb3RoIiA9ICJmb3Jlc3RncmVlbiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk9ubHkgUk5BIiA9ICJibHVlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiT25seSBBVEFDIiA9ICJvcmFuZ2UiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJOb25lIiA9ICJncmV5IikpIApgYGAKCiMgSW50ZWdyYXRpbmcgUk5BICYgQVRBQwoKV2Ugd2lsbCByZW1vdmUgYWxsIGNlbGxzIGZyb20gdGhlIHNjUk5BLXNlcSBkYXRhc2V0IHdoaWNoIGRvIG5vdCBwYXNzIHRoZSAKc2NBVEFDLXNlcSBRQyBhbmQgdmljZSB2ZXJzYS4KCmBgYHtyfQojcm5hX3NldXJhdF9maWx0IDwtIHN1YnNldChnYXN0cl9zZXVyYXQsIHBhc3NfYXRhY1FDID09ICJUcnVlIikKIyBhdGFjX3NldXJhdF9maWx0IDwtIHN1YnNldChhdGFjX3NldXJhdCwgcGFzc19ybmFRQyA9PSBUUlVFKQoKYGBgCgo=